<?php
	

use \GatewayWorker\Lib\Gateway;

include_once(dirname(__DIR__) .'/Module/Verification.class.php');
include_once(dirname(__DIR__) .'/Module/Socket.class.php');
include_once(dirname(__DIR__) .'/Module/Redis.class.php');
require_once dirname(__DIR__) . '/base.class.model.php';
class Public_Model extends Base_Model
{


	//扣除房卡或退还房卡
	protected function balanceTicket($room_id, $account_id, $spend_ticket_count){
		$timestamp = time();
		$MMYSQL = $this->initMysql();
		$MMYSQL->update(Room_Ticket)->set("ticket_count", "ticket_count-".$spend_ticket_count)->where("account_id=".$account_id)->query();

		//获取流水账
		$balance = 0;
		$balance_where = 'account_id='.$account_id.' and is_delete=0';
		$balance_sql = 'select balance from '.Room_Ticket_Journal.' where '.$balance_where.' order by journal_id desc';

		$balance_query = $MMYSQL->query($balance_sql);
		if(is_array($balance_query) && count($balance_query) > 0 ){
			$balance = $balance_query[0]['balance'];
		}

		//添加到流水账
		$journal_array['create_time'] = $timestamp;
		$journal_array['create_appid'] = "aid_".$account_id;
		$journal_array['update_time'] = $timestamp;
		$journal_array['update_appid'] = "aid_".$account_id;
		$journal_array['is_delete'] = G_CONST::IS_FALSE;
		$journal_array['account_id'] = $account_id;
		$journal_array['object_id'] = $room_id;
		$journal_array['object_type'] = 3;  //游戏

		$journal_array['extra'] = "";

		if($spend_ticket_count > 0){
			$journal_array['disburse'] = $spend_ticket_count;
			$journal_array['abstract'] = "炸金花";		//摘要
		} else {
			$journal_array['income'] = -$spend_ticket_count;
			$journal_array['abstract'] = "炸金花房卡退还";		//摘要
		}

		$journal_array['balance'] = $balance - $spend_ticket_count;
		if($journal_array['balance'] < 0)
		{
			$this->writeLog("balance negative balance: ".$balance." account_id: ".$account_id." room_id: ".$room_id);
			$journal_array['balance'] = 0;
		}
		$journal_id = $MMYSQL->insertReturnID(Room_Ticket_Journal,$journal_array);
	}


	//获取房间玩法设置
	protected function queryRoomSetting($room_id){
		$Redis_Model = Redis_Model::getModelObject();
		$replyArr = array("[roomid]"=>$room_id);
		$Room_Key = strtr(Redis_Const::Room_Key, $replyArr);
		$result = $Redis_Model->hgetallField($Room_Key);
		if(!isset($result[Redis_CONST::Room_Field_Scoreboard])){
			$result[Redis_CONST::Room_Field_Scoreboard] = "{}";
		}
		return $result;
	}

	protected function setHashTransaction($room_id)
	{
		$Redis_Model = Redis_Model::getModelObject();
		$replyArr = array("[roomid]"=>$room_id);
		$key = strtr(Redis_Const::Room_Key, $replyArr);

		$redisAuth = $Redis_Model->pingRedisAuth();
		if($redisAuth === G_CONST::EMPTY_STRING || !is_object($redisAuth))
		{
			$this->logMessage('error', "function(existsKey):redisAuth is empty string"." in file".__FILE__." on Line ".__LINE__);
			return false;
		}

	    $success = false;
	    $options = array(
	        'cas'   => true,    // Initialize with support for CAS operations
	        'watch' => $key,    // Key that needs to be WATCHed to detect changes
	        'retry' => 3,       // Number of retries on aborted transactions, after
	                            // which the client bails out with an exception.
	    );

	    $redisAuth->transaction($options, function ($tx) use ($key, &$success) {
	        $room_status = $tx->hget($key, Redis_Const::Room_Field_Status);
	        if (isset($room_status) && $room_status == 1) {
	            $tx->multi();   // With CAS, MULTI *must* be explicitly invoked.
	            $tx->hmset($key, array(Redis_Const::Room_Field_Status => 2));
	            $success =  true;

	        } else {
	        	$this->writeLog("room_status != 1");
	        	$success =  false;
	        }
	    });
	    return $success;
	}

	//设置房间状态   1等待中   2游戏中
	protected function setRoomStatusTransaction($room_id,$pre_status,$update_status)
	{
		$Redis_Model = Redis_Model::getModelObject();
		$replyArr = array("[roomid]"=>$room_id);
		$key = strtr(Redis_Const::Room_Key, $replyArr);
		
		$redisAuth = $Redis_Model->pingRedisAuth();
		if($redisAuth === G_CONST::EMPTY_STRING || !is_object($redisAuth))
		{
			$this->logMessage('error', "function(setRoomStatusTransaction):redisAuth is empty string"." in file".__FILE__." on Line ".__LINE__);
			return false;
		}

	    $success = false;
	    $options = array(
	        'cas'   => true,    // Initialize with support for CAS operations
	        'watch' => $key,    // Key that needs to be WATCHed to detect changes
	        'retry' => 3,       // Number of retries on aborted transactions, after
	                            // which the client bails out with an exception.
	    );

	    $redisAuth->transaction($options, function ($tx) use ($key,$pre_status,$update_status, &$success) {
	        $room_status = $tx->hget($key, Redis_CONST::Room_Field_Status);
	        if (isset($room_status) && $room_status == $pre_status) {
	            $tx->multi();   // With CAS, MULTI *must* be explicitly invoked.
	            $tx->hmset($key, array(Redis_Const::Room_Field_Status => $update_status));
	            $success =  true;

	        } else {
	        	$this->logMessage('error', "function(setRoomStatusTransaction):room_status error ".$pre_status." in file".__FILE__." on Line ".__LINE__);
	        	$success =  false;
	        }
	    });
	    return $success;
	}

	//开局
	protected function startGame($room_id, $passive_by_timer=false)
	{
		$timestamp = time();
		$Redis_Model = Redis_Model::getModelObject();
		$replyArr = array("[roomid]"=>$room_id);
		
		$Room_Key = strtr(Redis_Const::Room_Key, $replyArr);
		$Play_Key = strtr(Redis_Const::Play_Key, $replyArr);
		
		$ready_user = $this->queryReadyUser($room_id);
		$in_room_array = $this->queryInRoomUser($room_id);
		$ready_count = count($ready_user);
		$online_count = count($in_room_array);

		//准备人数 大于等于2 且 准备人数 等于 在线人数
		$this->writeLog("[$room_id] 准备:".$ready_count."人   "."在线:".$online_count."人");

		if($ready_count >=2)
		{
			if($passive_by_timer || $ready_count == $online_count){

				$pre_readyUser_ary = array();		//已准备用户数组-前
				$rear_readyUser_ary = array();		//已准备用户数组-后
				$is_rear = true;

				$ready_in_room_user = array_intersect($in_room_array, $ready_user); //在房的已准备用户
				if(count($ready_in_room_user) < 2){
					$this->writeLog("在房".$room_id."的已准备用户数量:".count($ready_in_room_user)." 不能开局 in file".__FILE__." on Line ".__LINE__);
					return false;
				}

				$success = $this->setRoomStatusTransaction($room_id, 1, 2);
				if(!$success){
					$this->writeLog("并发 start game，忽略。room id:".$room_id."。in file".__FILE__." on Line ".__LINE__);
					return false;
				}

				//开始游戏
				//参与游戏的都需要checked
				$ready_in_room_user = $this->ticketCheckTransaction($room_id, $ready_in_room_user);  //参与游戏玩家
				if(count($ready_in_room_user) < 2){	//异常情况
					$this->setRoomStatusTransaction($room_id, 2, 1);	//修正房间状态
					$this->writeLog("[$room_id]的参与玩家数:".count($ready_in_room_user)." 不能开局 in file".__FILE__." on Line ".__LINE__);
					return false;
				}

				$banker_id = $this->queryBanker($room_id);
				
				foreach($ready_in_room_user as $account_id)
				{
					if(in_array($account_id, $ready_in_room_user))	
					{
						if($is_rear)
						{
							$rear_readyUser_ary[] = $account_id;
						}
						else
						{
							$pre_readyUser_ary[] = $account_id;
						}
					}
					
					if($account_id == $banker_id)
					{
						$is_rear = false;
					}
				}
				
				$readyUser_ary = array_merge($pre_readyUser_ary,$rear_readyUser_ary);
				
				$next_banker_id = $readyUser_ary[0];

				if(!$passive_by_timer){
					//取消倒计时
					$this->deleteRoomTimer($room_id);
				}


				$Chip_Key = strtr(Redis_Const::Chip_Key, $replyArr);
				$SeenCard_Key = strtr(Redis_Const::SeenCard_Key, $replyArr);
				$Card_Key = strtr(Redis_Const::Card_Key, $replyArr);
				$PlayMember_Key = strtr(Redis_Const::PlayMember_Key, $replyArr);
				$AccountStatus_Key = strtr(Redis_Const::AccountStatus_Key, $replyArr);
				
				//删除每局玩家筹码hash
				$Redis_Model->deleteKey($Chip_Key);
				//删除每局玩家看牌标识hash
				$Redis_Model->deleteKey($SeenCard_Key);
				//删除每局玩家手牌hash
				$Redis_Model->deleteKey($Card_Key);

				
				$Chip_mkv = array();
				$Card_mkv = array();
				$play_member = array();  //游戏玩家队列
				$RoomStatus_mvk = array();

				$readyUserCount = count($readyUser_ary);  //游戏中玩家数量
				$player_cards = $this->dealCard($readyUserCount);  //发牌

				for ($i=0; $i < $readyUserCount; $i++) 
				{
					$account_id = $readyUser_ary[$i];
					//玩家状态变成闷牌状态
					$RoomStatus_mvk[$account_id] = Game::AccountStatus_Invisible;
				
					//设置每局玩家手牌hash
					$Card_mkv[$account_id] = $player_cards[$i];
				}

				//设置每局玩家顺序list
				$play_member = $readyUser_ary;
				
				//$mset_result = $Redis_Model->hmsetField($Chip_Key,$Chip_mkv);
				$mset_result = $Redis_Model->hmsetField($Card_Key,$Card_mkv);
				$mset_result = $Redis_Model->hmsetField($AccountStatus_Key,$RoomStatus_mvk);

				//删除每局玩家顺序list 再装入本局玩家
				$Redis_Model->deleteKey($PlayMember_Key);
				$push_result = $Redis_Model->pushList($is_rpush=0,$is_pushx=0,$PlayMember_Key,$play_member); //lpush
				
				//重设每局游戏参数
				$parameter_ary[Redis_CONST::Play_Field_PoolScore] = 0;// Game::Default_Score * $ready_count;
				$parameter_ary[Redis_CONST::Play_Field_Benchmark] = Game::Default_Score;

				$parameter_ary[Redis_CONST::Play_Field_ActiveUser] =  $next_banker_id;
				$mset_result = $Redis_Model->hmsetField($Play_Key,$parameter_ary);

				
				$Room_mkv[Redis_CONST::Room_Field_Status] = 2;  //房间状态，1等待、2进行中、3关闭
				$Room_mkv[Redis_CONST::Room_Field_Banker] = $next_banker_id;
				$mset_result = $Redis_Model->hmsetField($Room_Key,$Room_mkv);

				//房间轮数与局数更新
				$this->updateGameNumberRound($room_id);
                $setting = $this->queryRoomSetting($room_id);
				//底注
				foreach($readyUser_ary as $account_id)
				{
					$this->balanceScore($room_id, $account_id, $setting[Redis_Const::Room_Field_DefaultScore]);
				}

				$player_status = array();
				foreach ($play_member as $player_id) {
					if($player_id == $next_banker_id){
						$player_status[] = array(
								"account_id"=> $player_id,
						        "account_status"=> Game::AccountStatus_Invisible,		 //5; 初始是闷牌状态
						        "online_status" => $this->queryOnlineStatus($room_id, $player_id),
						        "playing_status"=> Game::PlayingStatus_Betting, //2;  下注中
						        "limit_time" => Game::LimitTime_Betting,
								'can_open' =>  0,
								'can_look' => $this->lookConditon($room_id, $player_id)
							);
					} else {
						$player_status[] = array(
								"account_id"=> $player_id,
						        "account_status"=> Game::AccountStatus_Invisible,		 //5; 初始是闷牌状态
						        "online_status" => $this->queryOnlineStatus($room_id, $player_id),
						        "playing_status"=> Game::PlayingStatus_Waiting, //1 等待别人中
						        "limit_time" => 0
							);
					}
				}

				//设置自动弃牌定时器
				$this->setupDiscardPassiveTimer($room_id, $next_banker_id);

				//推送开始
				$arr = array("result"=>0,"operation"=>"GameStart","data"=>$player_status,"result_message"=>"游戏开始了");
				$this->pushMessageToGroup($room_id, $arr);

			} else {
				if($this->getTimerTime($room_id) == -1 ){
					// $this->queryTimerId($room_id) == -1   只有第二个人的准备才触发倒计时   $ready_count == 2 || 

					if($ready_count == 2){	//第二个人准备就删掉自动清理房间定时器吧
						$this->deleteRoomTimer($room_id);
					}

					$this->setupStartGamePassiveTimer($room_id);
				}
			}
		}
		
		return true;
	}


	//设置 自动弃牌 定时器
	protected function setupDiscardPassiveTimer($room_id, $account_id){

		$callback_array = array(
			'operation' => "DiscardPassive",
			'room_id' => $room_id,
			'data' => array(
				'account_id' => $account_id
				)
			);
		$arr = array(
			'operation' => "BuildTimer",
			'room_id'   => $room_id,
			'data' => array(
				'limit_time' => Game::LimitTime_Betting,
				'callback_array' => $callback_array
				)
			);
		$this->sendToTimerServer($arr);

		$this->setTimerTime($room_id);	//分开、提前设置时间
	}

	//设置 自动开局 定时器
	protected function setupStartGamePassiveTimer($room_id){

		$limit_time = $this->queryGameNumber($room_id) > 0 ? Game::LimitTime_Ready : Game::LimitTime_StartGame;

		$callback_array = array(
			'operation' => "StartGamePassive",
			'room_id' => $room_id,
			'data' => array(
				)
			);
		$arr = array(
			'operation' => "BuildTimer",
			'room_id'   => $room_id,
			'data' => array(
				'limit_time' => $limit_time,
				'callback_array' => $callback_array
				)

			);
		$this->sendToTimerServer($arr);

		$this->setTimerTime($room_id);	//分开、提前设置时间

		$arr = array("result"=>0,"operation"=>"StartLimitTime","data"=>array('limit_time' => $limit_time),"result_message"=>"开始倒计时");
		$this->pushMessageToGroup($room_id, $arr);
	}


	//设置 清理房间 定时器
	protected function setupClearRoomPassiveTimer($room_id){

		$this->writeLog("[$room_id] 设置自动清扫房间定时器");
		$callback_array = array(
			'operation' => "ClearRoomPassive",
			'room_id' => $room_id,
			'data' => array(
				)
			);
		$arr = array(
			'operation' => "BuildTimer",
			'room_id'   => $room_id,
			'data' => array(
				'limit_time' => Game::LimitTime_ClearRoom,
				'callback_array' => $callback_array
				)
			);
		$this->sendToTimerServer($arr);

		//$this->setTimerTime($room_id);	//分开、提前设置时间   (这个清扫定时器就暂不设置时间了)
	}


	//删除定时器
	protected function deleteRoomTimer($room_id){

		$timer_id = $this->queryTimerId($room_id);
		if($timer_id > 0){
			$arr = array(
				'operation' => "DeleteTimer",
				'room_id'   => $room_id,
				'data' => array(
					'timer_id' => $timer_id
					)

				);
			$this->sendToTimerServer($arr);
		}
		$this->updateTimer($room_id, -1);
	}

	//查询倒计时
	protected function queryCountdown($room_id, $limit){

		$Redis_Model = Redis_Model::getModelObject();
		$replyArr = array("[roomid]"=>$room_id);
		$Play_Key = strtr(Redis_Const::Play_Key, $replyArr);
		
		$timer_time = $Redis_Model->hgetField($Play_Key,Redis_Const::Play_Field_TimerTime);

		if($timer_time > 0){
			$countdown = $limit - time() + $timer_time;
			return $countdown > 0 ? $countdown : 0;
		} else {

			return 0;
		}
	}

	//设置或取消(timer_id  -1)定时器
	protected function updateTimer($room_id, $timer_id){

		$Redis_Model = Redis_Model::getModelObject();
		$replyArr = array("[roomid]"=>$room_id);
		$Play_Key = strtr(Redis_Const::Play_Key, $replyArr);
		
		$mkv[Redis_Const::Play_Field_TimerId] = $timer_id;
		if($timer_id > 0){
			$mkv[Redis_Const::Play_Field_TimerTime] = time();
		} else {
			$mkv[Redis_Const::Play_Field_TimerTime] = -1;
		}

		$mset_result = $Redis_Model->hmsetField($Play_Key,$mkv);
	}

	protected function setTimerId($room_id, $timer_id){
		$Redis_Model = Redis_Model::getModelObject();
		$replyArr = array("[roomid]"=>$room_id);
		$Play_Key = strtr(Redis_Const::Play_Key, $replyArr);
		$mkv[Redis_Const::Play_Field_TimerId] = $timer_id;
		$mset_result = $Redis_Model->hmsetField($Play_Key,$mkv);
	}
	protected function setTimerTime($room_id){
		$Redis_Model = Redis_Model::getModelObject();
		$replyArr = array("[roomid]"=>$room_id);
		$Play_Key = strtr(Redis_Const::Play_Key, $replyArr);
		$mkv[Redis_Const::Play_Field_TimerTime] = time();
		$mset_result = $Redis_Model->hmsetField($Play_Key,$mkv);
	}
	protected function getTimerTime($room_id){
		$Redis_Model = Redis_Model::getModelObject();
		$replyArr = array("[roomid]"=>$room_id);
		$Play_Key = strtr(Redis_Const::Play_Key, $replyArr);
		$timer_time = $Redis_Model->hgetField($Play_Key,Redis_Const::Play_Field_TimerTime);
		return $timer_time > 0 ? $timer_time : -1;
	}

	//获取定时器id
	protected function queryTimerId($room_id){

		$Redis_Model = Redis_Model::getModelObject();
		$replyArr = array("[roomid]"=>$room_id);
		$Play_Key = strtr(Redis_Const::Play_Key, $replyArr);
		$result = $Redis_Model->hgetField($Play_Key,Redis_Const::Play_Field_TimerId);
		return $result > 0 ? $result : -1;
	}

	//更新房间状态
	protected function updateRoomStatus($room_id, $status){

		$Redis_Model = Redis_Model::getModelObject();
		$replyArr = array("[roomid]"=>$room_id);
		$Room_Key = strtr(Redis_Const::Room_Key, $replyArr);
		
		$mkv[Redis_Const::Room_Field_Status] = $status;
		$mset_result = $Redis_Model->hmsetField($Room_Key,$mkv);
	}

	//重新设置所有用户状态为未准备
	protected function resetAllAccountStatus($room_id, $reset_status=Game::AccountStatus_Notready){

		$Redis_Model = Redis_Model::getModelObject();
		$replyArr = array("[roomid]"=>$room_id);
		$AccountStatus_Key = strtr(Redis_Const::AccountStatus_Key, $replyArr);

		$mkv = array();
		$members = $this->queryRoomMembers($room_id);
		if(is_array($members) && count($members)){
			foreach ($members as $account_id) {
				$pre_status = $this->queryAccountStatus($room_id, $account_id);
				$status = ($pre_status == Game::AccountStatus_Initial) ? Game::AccountStatus_Initial : $reset_status;

				$mkv[$account_id] = $status;
			}
		}
		$mset_result = $Redis_Model->hmsetField($AccountStatus_Key,$mkv);  //用户状态
	}

	//重新设置所有用户分数为0
	protected function resetAllAccountScore($room_id){

		$Redis_Model = Redis_Model::getModelObject();
		$replyArr = array("[roomid]"=>$room_id);
		$RoomScore_Key = strtr(Redis_Const::RoomScore_Key, $replyArr);

		$mkv = array();
		$members = $this->queryRoomMembers($room_id);
		if(is_array($members) && count($members)){
			foreach ($members as $account_id) {
				$mkv[$account_id] = 0;
			}
		}
		$mset_result = $Redis_Model->hmsetField($RoomScore_Key,$mkv);  //用户状态
	}

	//观战功能 获取房间观战者队列
	protected function queryGuestList($room_id){
		$Redis_Model = Redis_Model::getModelObject();
		$replyArr = array("[roomid]"=>$room_id);
		$RoomGuest_Key = strtr(Redis_Const::RoomGuest_Key, $replyArr);
		$guests = $Redis_Model->lrangeList($RoomGuest_Key);
		if(is_array($guests) ){
			return $guests;
		} else {
			return array();
		}
	}

	//获取房间状态
	protected function queryRoomStatus($room_id){

		$Redis_Model = Redis_Model::getModelObject();
		$replyArr = array("[roomid]"=>$room_id);
		$Room_Key = strtr(Redis_Const::Room_Key, $replyArr);
		
		$result = $Redis_Model->hgetField($Room_Key,Redis_Const::Room_Field_Status);
		return $result;
	}

	//获取房间每轮需要消耗的房卡数
	protected function queryTicketCount($room_id){

		$Redis_Model = Redis_Model::getModelObject();
		$replyArr = array("[roomid]"=>$room_id);
		$Room_Key = strtr(Redis_Const::Room_Key, $replyArr);
		
		$result = $Redis_Model->hgetField($Room_Key,Redis_Const::Room_Field_TicketCount);
		return $result > 0 ? $result : 1;
	}

	//获取房间一轮总局数
	protected function queryTotalNum($room_id){

		$Redis_Model = Redis_Model::getModelObject();
		$replyArr = array("[roomid]"=>$room_id);
		$Room_Key = strtr(Redis_Const::Room_Key, $replyArr);
		
		$result = $Redis_Model->hgetField($Room_Key,Redis_Const::Room_Field_TotalNum);
		return $result;
	}

	//获取房间当前局数
	protected function queryGameNumber($room_id){

		$Redis_Model = Redis_Model::getModelObject();
		$replyArr = array("[roomid]"=>$room_id);
		$Room_Key = strtr(Redis_Const::Room_Key, $replyArr);
		
		$result = $Redis_Model->hgetField($Room_Key,Redis_Const::Room_Field_GameNum);
		return $result;
	}

	//自增长房间当前局数、轮数
	protected function updateGameNumberRound($room_id){

		$Redis_Model = Redis_Model::getModelObject();
		$replyArr = array("[roomid]"=>$room_id);
		$Room_Key = strtr(Redis_Const::Room_Key, $replyArr);
		
		$game_num = $Redis_Model->hincrbyField($Room_Key, Redis_Const::Room_Field_GameNum, 1);
		$this->writeLog("[$room_id] 新的一局 :".$game_num);

		if($game_num == 1){
			//设置开局时间
			$this->updateStartTime($room_id);
		}

	}

	//更新用户状态
	protected function updateAccountStatus($room_id, $account_id, $status){

		$Redis_Model = Redis_Model::getModelObject();
		$replyArr = array("[roomid]"=>$room_id);
		$AccountStatus_Key = strtr(Redis_Const::AccountStatus_Key, $replyArr);
		
		$mkv[$account_id] = $status;
		$mset_result = $Redis_Model->hmsetField($AccountStatus_Key,$mkv);

		//广播用户状态改变
		$noty_arr = array(
			'account_id' => $account_id,
			'account_status'=>$status,
			'online_status'=>$this->queryOnlineStatus($room_id, $account_id)
			);
		$this->writeLog("[$room_id] ($account_id) 状态改变 ". $status);
		$this->notyUpdateAccountStatusToGroup($room_id, $noty_arr);
	}
	
	//获取在线状态
	protected function queryOnlineStatus($room_id, $account_id){

		$replyArr = array("[roomid]"=>$room_id,"[accountid]"=>$account_id);
		$RoomUser_UID = strtr(Game::RoomUser_UID, $replyArr);

		return Gateway::isUidOnline($RoomUser_UID);
	}


	//获取准备人数
	protected function queryReadyCount($room_id){

		$Redis_Model = Redis_Model::getModelObject();
		$replyArr = array("[roomid]"=>$room_id);
		$AccountStatus_Key = strtr(Redis_Const::AccountStatus_Key, $replyArr);
		
		$result = $Redis_Model->hgetallField($AccountStatus_Key);
		$count = 0;
		if(Redis_CONST::DATA_NONEXISTENT !== $result){
			foreach ($result as $account_id => $status) {
				if($status == Game::AccountStatus_Ready){
					$count++;
				}
			}
		}
		return $count;
	}

	//获取准备的人
	protected function queryReadyUser($room_id){

		$Redis_Model = Redis_Model::getModelObject();
		$replyArr = array("[roomid]"=>$room_id);
		$AccountStatus_Key = strtr(Redis_Const::AccountStatus_Key, $replyArr);
		
		$ready_user_array = [];
		$result = $Redis_Model->hgetallField($AccountStatus_Key);
		if(Redis_CONST::DATA_NONEXISTENT !== $result){
			foreach ($result as $account_id => $status) {
				if($status == Game::AccountStatus_Ready){
					$ready_user_array[] = $account_id;
				}
			}
		}
		return $ready_user_array;
	}
	//观战功能 (修改) 获取在房(入座)的人
	protected function queryInRoomUser($room_id){
		$in_room_user_array = [];
		$room_members = $this->queryRoomMembers($room_id);
		$guests = $this->queryGuestList($room_id);
		$room_members = array_diff($room_members, $guests);

		foreach ($room_members as $account_id) {
			if($this->queryOnlineStatus($room_id, $account_id)){
				$in_room_user_array[] = $account_id;
			}
		}
		return $in_room_user_array;
	}

	//获取用户状态
	protected function queryAccountStatus($room_id, $account_id){

		$Redis_Model = Redis_Model::getModelObject();
		$replyArr = array("[roomid]"=>$room_id);
		$AccountStatus_Key = strtr(Redis_Const::AccountStatus_Key, $replyArr);
		
		$result = $Redis_Model->hgetField($AccountStatus_Key,$account_id);
		return $result;
	}

	//获取用户是否已经看牌
	protected function querySeenCard($room_id, $account_id){

		$Redis_Model = Redis_Model::getModelObject();
		$replyArr = array("[roomid]"=>$room_id);
		$SeenCard_Key = strtr(Redis_Const::SeenCard_Key, $replyArr);
		$result = $Redis_Model->hgetField($SeenCard_Key,$account_id);
		return $result == 1 ? 1 : 0;
	}

	//获取用户积分
	protected function queryAccountScore($room_id, $account_id){

		$Redis_Model = Redis_Model::getModelObject();
		$replyArr = array("[roomid]"=>$room_id);
		$RoomScore_Key = strtr(Redis_Const::RoomScore_Key, $replyArr);
		
		$result = $Redis_Model->hgetField($RoomScore_Key,$account_id);
		return $result;
	}

	//下注平衡积分
	protected function balanceScore($room_id, $account_id, $score){

		$Redis_Model = Redis_Model::getModelObject();
		$replyArr = array("[roomid]"=>$room_id);
		$RoomScore_Key = strtr(Redis_Const::RoomScore_Key, $replyArr);
		$Play_Key = strtr(Redis_Const::Play_Key, $replyArr);
		$Chip_Key = strtr(Redis_Const::Chip_Key, $replyArr);
		
		$mset_result = $Redis_Model->hincrbyField($RoomScore_Key,$account_id, 0 - $score); //总分 减少
		$mset_result = $Redis_Model->hincrbyField($Play_Key,Redis_Const::Play_Field_PoolScore, $score);	//分数池 增加
		$mset_result = $Redis_Model->hincrbyField($Chip_Key,$account_id, $score);
	}

	//获胜平衡积分  account_id 下注者
	protected function balanceWinnerScore($room_id, $winners, $account_id=-1){

		$winner_score_dict = array();
		$count = count($winners);
		if($count < 1){
			return array();
		}

		$Redis_Model = Redis_Model::getModelObject();
		$replyArr = array("[roomid]"=>$room_id);
		$RoomScore_Key = strtr(Redis_Const::RoomScore_Key, $replyArr);
		$Play_Key = strtr(Redis_Const::Play_Key, $replyArr);
		$Chip_Key = strtr(Redis_Const::Chip_Key, $replyArr);

		$pool_score = $Redis_Model->hgetField($Play_Key,Redis_Const::Play_Field_PoolScore);
		$per_score = intval($pool_score/$count);
		$remain_score = $pool_score - $per_score * ($count-1) ;

		foreach ($winners as $winner_id) {
			if($winner_id == $account_id){
				$win_score = $remain_score;
			} else {
				$win_score = $per_score;
			}
			$Redis_Model->hincrbyField($RoomScore_Key, $winner_id, $win_score); //个人总分 增加 
			$winner_score_dict[$winner_id] = $win_score;
		}
		$Redis_Model->hmsetField($Play_Key, array(Redis_Const::Play_Field_PoolScore => 0));	//分数池 清零

		return $winner_score_dict;
	}

	protected function caculateCardValue($room_id, $player_id){
		$Redis_Model = Redis_Model::getModelObject();
		$replyArr = array("[roomid]"=>$room_id);
		$Card_Key = strtr(Redis_Const::Card_Key, $replyArr);
		$card_str = $Redis_Model->hgetField($Card_Key, $player_id);

		$cards = explode(",", $card_str);
		$value = $this->_cardValue($cards);
		return $value;
	}
	protected function _cardValue($cards){
		
		if(count($cards)!=3){
			return 0;
		}
		$value = 0;
		$suits = array();
		$points= array();
		foreach ($cards as $card) {
			$suits[] = substr($card, 0, 1);
			$points[] = substr($card, 1);
		}

		//A替换成数值14
		for ($i=0; $i < count($points); $i++) { 
			if($points[$i] == 1){
				$points[$i] = 14;
			}
		}

		rsort($points, SORT_NUMERIC);  //大到小排序
		$points_val_str = str_pad($points[0], 2, "0", STR_PAD_LEFT) . str_pad($points[1], 2, "0", STR_PAD_LEFT) . str_pad($points[2], 2, "0", STR_PAD_LEFT);
		//牌型  0未知(因别人弃牌而胜) 1高牌 2对子 3顺子 4同花 5同花顺 6三条
		if($points[0] == $points[2]){ //三条
			$value = "6".$points_val_str;
		} else if($points[0] == $points[1]){ //对子
			$value = "2".$points_val_str;
		} else if($points[1] == $points[2]){ //对子
			$value = "2".str_pad($points[2], 2, "0", STR_PAD_LEFT) . str_pad($points[1], 2, "0", STR_PAD_LEFT) . str_pad($points[0], 2, "0", STR_PAD_LEFT);
		} else if($points[0] == $points[2] + 2){ //顺子
			$card_type = ($suits[0] == $suits[1] && $suits[1] == $suits[2]) ? 5 : 3;
			$value = $card_type.$points_val_str;
		} else if($points[0]==14&&$points[1]==3&&$points[2]==2){ //顺子
			$card_type = ($suits[0] == $suits[1] && $suits[1] == $suits[2]) ? 5 : 3;
			$value = $card_type."010203";
		} else if($suits[0] == $suits[1] && $suits[1] == $suits[2]){  //同花
			$value = "4".$points_val_str;
		} else {	//高牌
			$value = "1".$points_val_str;
		}
		return $value;
	}

	protected function queryCardInfo($room_id, $player_id){
		$Redis_Model = Redis_Model::getModelObject();
		$replyArr = array("[roomid]"=>$room_id);
		$Card_Key = strtr(Redis_Const::Card_Key, $replyArr);
		$card_str = $Redis_Model->hgetField($Card_Key, $player_id);
		$this->writeLog("[$room_id] ($player_id) 手牌:".$card_str);
		if(Redis_CONST::DATA_NONEXISTENT === $card_str || ""==trim($card_str)){  //异常状态返回空数组
			$this->writeLog("function(queryCardInfo):异常状态返回空数组"." in file".__FILE__." on Line ".__LINE__);
			return array();
		}
		$cards = explode(",", $card_str);

		return $cards;
	}


	//返回积分榜
	protected function queryScoreboard($room_id){

		$Redis_Model = Redis_Model::getModelObject();
		$replyArr = array("[roomid]"=>$room_id);
		$Room_Key = strtr(Redis_Const::Room_Key, $replyArr);
		
		$result = $Redis_Model->hgetField($Room_Key,Redis_Const::Room_Field_Scoreboard);
		if($result !== Redis_Const::DATA_NONEXISTENT){
			$arr = json_decode($result);
		} else {
			$arr = new stdClass();
		}
		return $arr;
	}


	//获取房间积分榜 json string
	protected function queryRoomScoreboard($room_id){

		$Redis_Model = Redis_Model::getModelObject();
		$replyArr = array("[roomid]"=>$room_id);
		$Room_Key = strtr(Redis_Const::Room_Key, $replyArr);
		
		$result = $Redis_Model->hgetField($Room_Key,Redis_Const::Room_Field_Scoreboard);
		return $result;
	}


	//获取叫分基准
	protected function queryBenchmark($room_id){
		$Redis_Model = Redis_Model::getModelObject();
		$replyArr = array("[roomid]"=>$room_id);
		$Play_Key = strtr(Redis_Const::Play_Key, $replyArr);
		$result = $Redis_Model->hgetField($Play_Key,Redis_Const::Play_Field_Benchmark);
		return $result;
	}
	//设置叫分基准
	protected function updateBenchmark($room_id, $benchmark){
		if($benchmark < 0){
			return false;
		}

		$Redis_Model = Redis_Model::getModelObject();
		$replyArr = array("[roomid]"=>$room_id);
		$Play_Key = strtr(Redis_Const::Play_Key, $replyArr);
		
		$mkv[Redis_Const::Play_Field_Benchmark] = $benchmark;
		$mset_result = $Redis_Model->hmsetField($Play_Key,$mkv);
	}

	//获取分数池分数
	protected function queryPoolScore($room_id){
		$Redis_Model = Redis_Model::getModelObject();
		$replyArr = array("[roomid]"=>$room_id);
		$Play_Key = strtr(Redis_Const::Play_Key, $replyArr);
		$result = $Redis_Model->hgetField($Play_Key,Redis_Const::Play_Field_PoolScore);
		return $result > 0 ? $result : 0;
	}

	//获取庄家account_id
	protected function queryBanker($room_id){
		$Redis_Model = Redis_Model::getModelObject();
		$replyArr = array("[roomid]"=>$room_id);
		$Room_Key = strtr(Redis_Const::Room_Key, $replyArr);
		$result = $Redis_Model->hgetField($Room_Key,Redis_Const::Room_Field_Banker);
		return $result > 0 ? $result : -1;
	}
	//获取房主id
	protected function queryCreator($room_id){
		$Redis_Model = Redis_Model::getModelObject();
		$replyArr = array("[roomid]"=>$room_id);
		$Room_Key = strtr(Redis_Const::Room_Key, $replyArr);
		$result = $Redis_Model->hgetField($Room_Key,Redis_Const::Room_Field_Creator);
		return $result;
	}

	//获取激活的操作中的用户
	protected function queryActiveUser($room_id){
		$Redis_Model = Redis_Model::getModelObject();
		$replyArr = array("[roomid]"=>$room_id);
		$Play_Key = strtr(Redis_Const::Play_Key, $replyArr);
		$result = $Redis_Model->hgetField($Play_Key,Redis_Const::Play_Field_ActiveUser);
		return  $result > 0 ? $result : -1;
	}

	//获取开局时间
	protected function queryStartTime($room_id){
		$Redis_Model = Redis_Model::getModelObject();
		$replyArr = array("[roomid]"=>$room_id);
		$Room_Key = strtr(Redis_Const::Room_Key, $replyArr);
		$result = $Redis_Model->hgetField($Room_Key,Redis_Const::Room_Field_StartTime);
		return  $result > 0 ? $result : -1;
	}
	//更新游戏开局时间
	protected function updateStartTime($room_id)
	{
		$Redis_Model = Redis_Model::getModelObject();
		$replyArr = array("[roomid]"=>$room_id);
		$Room_Key = strtr(Redis_Const::Room_Key, $replyArr);
		
		$mkv[Redis_Const::Room_Field_StartTime] = time();
		$mset_result = $Redis_Model->hmsetField($Room_Key,$mkv);
		return $mset_result;
	}

	//轮流
	protected function takeTurns($room_id){
		$Redis_Model = Redis_Model::getModelObject();
		$replyArr = array("[roomid]"=>$room_id);
		$PlayMember_Key = strtr(Redis_Const::PlayMember_Key, $replyArr);
		$result = $Redis_Model->rotationList($PlayMember_Key);

		$list = $Redis_Model->lrangeList($PlayMember_Key,-1,-1);  //队列最右边是当前操作用户
		if($list){
			$account_id = $list[0];
		} else {
			$account_id = -1;
		}

		$Play_Key = strtr(Redis_Const::Play_Key, $replyArr);
		$mkv[Redis_Const::Play_Field_ActiveUser] = $account_id;

		$mset_result = $Redis_Model->hmsetField($Play_Key,$mkv);

		return $account_id;
	}

	//获取游戏中的人数
	protected function queryPlayMemberCount($room_id){
		$Redis_Model = Redis_Model::getModelObject();
		$replyArr = array("[roomid]"=>$room_id);
		$PlayMember_Key = strtr(Redis_Const::PlayMember_Key, $replyArr);
		$result = $Redis_Model->llenList($PlayMember_Key);
		return $result;
	}

	//从游戏中队列踢出
	protected function removeFromPlayMember($room_id, $account_id){
		$Redis_Model = Redis_Model::getModelObject();
		$replyArr = array("[roomid]"=>$room_id);
		$PlayMember_Key = strtr(Redis_Const::PlayMember_Key, $replyArr);

		$Redis_Model->lremList($PlayMember_Key, 0, $account_id);

		$list = $Redis_Model->lrangeList($PlayMember_Key,-1,-1);  //队列最右边是当前操作用户
		if($list){
			$active_id = $list[0];
		} else {
			$active_id = -1;
		}
		$Play_Key = strtr(Redis_Const::Play_Key, $replyArr);
		$mkv[Redis_Const::Play_Field_ActiveUser] = $active_id;
		$mset_result = $Redis_Model->hmsetField($Play_Key,$mkv);

		return $active_id;
	}

	//推消息
	protected function pushMessageToGroup($room_id, $msg_arr, $exclude_client_id=null){
		$msg = $this->_JSON($msg_arr);
		Gateway::sendToGroup($room_id, $msg, $exclude_client_id);
	}
	protected function pushMessageToAccount($room_id, $account_id, $msg_arr){
		$replyArr = array("[roomid]"=>$room_id,"[accountid]"=>$account_id);
		$RoomUser_UID = strtr(Game::RoomUser_UID, $replyArr);
		$msg = $this->_JSON($msg_arr);
		Gateway::sendToUid($RoomUser_UID, $msg);
	}
	protected function pushMessageToCurrentClient($msg_arr){
		$msg = $this->_JSON($msg_arr);
		Gateway::sendToCurrentClient($msg);
	}

	//广播用户状态改变
	protected function notyUpdateAccountStatusToGroup($room_id, $noty_arr, $exclude_client_id=null){

		if(!isset($noty_arr['account_id']) || !isset($noty_arr['account_status']) ){
			$this->writeLog("function(notyUpdateAccountStatusToGroup):lack of params"." in file".__FILE__." on Line ".__LINE__);
			return false;
		}

		$msg_arr = array("result"=>"0","operation"=>"UpdateAccountStatus","data"=>$noty_arr,"result_message"=>"用户状态改变");
		$this->pushMessageToGroup($room_id, $msg_arr, $exclude_client_id=null);
	}


	//是否经过了第一轮下注，经过了才能比牌
	protected function pkChipConditon($room_id, $account_id){

		$Redis_Model = Redis_Model::getModelObject();
		$replyArr = array("[roomid]"=>$room_id);

		$setting = $this->queryRoomSetting($room_id);
		$disable_pk_score=isset($setting[Redis_Const::Room_Field_DisablePkScore]) ?$setting[Redis_Const::Room_Field_DisablePkScore]:0;

		if($disable_pk_score){
			if($this->queryPoolScore($room_id) < $disable_pk_score){
				return 0;
			} 
		} 

		$Chip_Key = strtr(Redis_Const::Chip_Key, $replyArr);
		$betScore = $Redis_Model->hgetField($Chip_Key, $account_id);
		if($betScore <= $setting[Redis_Const::Room_Field_DefaultScore] ){
			return 0;
		}
		return 1;
	}

	//是否经过了第一轮下注，经过了才能看牌
	protected function lookConditon($room_id, $account_id){
			$Redis_Model = Redis_Model::getModelObject();
			$replyArr = array("[roomid]"=>$room_id);
	
			$setting = $this->queryRoomSetting($room_id);
			$disable_look=isset($setting[Redis_Const::Room_Field_DisableLook]) ?$setting[Redis_Const::Room_Field_DisableLook]:0;
	
			if($disable_look){
				$Chip_Key = strtr(Redis_Const::Chip_Key, $replyArr);
				$betScore = $Redis_Model->hgetField($Chip_Key, $account_id);
				if($betScore <= $setting[Redis_Const::Room_Field_DefaultScore] ){
					return 0;
				} 
			} 
			return 1;
	}

	//通知用户下注
	protected function notyUserToBet($room_id, $account_id){

		$can_open = 0;
		$pk_user = array();
		if($this->pkChipConditon($room_id, $account_id)){
			$pk_user = $this->queryPkUser($room_id, $account_id);
			if(count($pk_user) > 0){
				$can_open = 1;
			}
		}

		//$this->writeLog("轮到用户".$account_id. "下注 (can_open:". $can_open .")");

		//设置自动弃牌定时器
		$this->setupDiscardPassiveTimer($room_id, $account_id);

		$noty_arr = array(
			'account_id' => $account_id,
			'playing_status' => Game::PlayingStatus_Betting,
			'limit_time'	 => Game::LimitTime_Betting,
			'can_open' => $can_open,
			'pk_user' => $pk_user,
			'can_look' => $this->lookConditon($room_id, $account_id)
			);
		$msg_arr = array("result"=>"0","operation"=>"NotyChooseChip","data"=>$noty_arr,"result_message"=>"通知下注");
		$this->pushMessageToGroup($room_id, $msg_arr);
	}

	public function queryPkUser($room_id, $account_id){
		$Redis_Model = Redis_Model::getModelObject();
		$replyArr = array("[roomid]"=>$room_id);
		$PlayMember_Key = strtr(Redis_Const::PlayMember_Key, $replyArr);
		$players = $Redis_Model->lrangeList($PlayMember_Key);

		$other_players = array();	
		foreach ($players as $player_id) {
			if($player_id != $account_id){
				$other_players[] = $player_id;
			}
		}
		$other_count = count($other_players) ;
		if($other_count == 1){
			$pk_user = $other_players;
		} else {
			$pk_user = array();
			foreach ($other_players as $player_id) {
				$status = $this->queryAccountStatus($room_id, $player_id);
				if($status == Game::AccountStatus_Visible){	//对方是看牌状态才能比牌
					$pk_user[] = $player_id;
				}
			}
			if(count($pk_user) < $other_count ){ //有人闷牌
				$setting = $this->queryRoomSetting($room_id);
				$disable_pk_men=isset($setting[Redis_Const::Room_Field_DisablePkMen]) ?$setting[Redis_Const::Room_Field_DisablePkMen]:0;
				if($disable_pk_men){
					$pk_user = array();
				}
			}
		}
		return $pk_user;
	}
	protected function queryInRoomPlay($room_id){
		$in_room_user_array = [];
		$room_members = $this->queryRoomMembers($room_id);
		$guests = $this->queryGuestList($room_id);
		$room_members = array_diff($room_members, $guests);

		foreach ($room_members as $account_id) {
			if($this->queryOnlineStatus($room_id, $account_id) && $this->queryAccountStatus($room_id,$account_id)>2){
				$in_room_user_array[] = $account_id;
			}
		}
		return $in_room_user_array;
	}
	protected function queryInGamePlay($room_id){
		$Redis_Model = Redis_Model::getModelObject();
		$Card_Key = strtr(Redis_Const::Card_Key, ['[roomid]'=>$room_id]);
		$card_array = $Redis_Model->hgetallField($Card_Key);
		$in_play = array_keys($card_array);
//		$room_members = $this->queryRoomMembers($room_id);
//		$guests = $this->queryGuestList($room_id);
//		$room_members = array_diff($room_members, $guests);
//		$in_play = [];
//		foreach ($room_members as $account_id){
//			if($this->queryOnlineStatus($room_id, $account_id) && $this->queryAccountStatus($room_id,$account_id)>2){
//				$in_play[] = $account_id;
//			}
//		}
		return $in_play;
	}
//获取底分分数
	 protected function queryXipaiScore($room_id){
		 $Redis_Model = Redis_Model::getModelObject();
		 $replyArr = array("[roomid]"=>$room_id);
		 $Room_Key = strtr(Redis_Const::Room_Key, $replyArr);
		 $result = $Redis_Model->hgetField($Room_Key,Redis_Const::Room_Field_XiPai);
		 return $result;
	 }
	 //喜牌平衡积分
	 protected function balanceXipaiScore($room_id, $winner_id){
		 if (!is_array($winner_id)){
			 $winner_id = [$winner_id];
		 }
		 $Redis_Model = Redis_Model::getModelObject();
		 $replyArr = array("[roomid]"=>$room_id);
		 $RoomScore_Key = strtr(Redis_Const::RoomScore_Key, $replyArr);

		 $score = $this->queryXipaiScore($room_id);
		 $this->writeLog( "[$room_id]喜牌：$score");
		 $players = $this->queryInGamePlay($room_id);
		 $account_count = count($players);
		 $xipai_score_dict = [];
		 $this->writeLog("[$room_id]赢家：".json_encode($winner_id));
		 $this->writeLog("[$room_id]原积分：".json_encode($Redis_Model->hgetallField($RoomScore_Key)));
		 foreach ($players as $mem_id) {
			 if(in_array($mem_id,$winner_id )){
				 $this->writeLog("[$room_id][$mem_id]：喜牌+". ($score*($account_count-count($winner_id))));
				 $Redis_Model->hincrbyField($RoomScore_Key, $mem_id, $score*($account_count-count($winner_id)));
				 $xipai_score_dict[$mem_id] = "+".$score*($account_count-count($winner_id));
			 } else {
				 $this->writeLog( "[$room_id][$mem_id]：喜牌-".$score*count($winner_id));
				 $Redis_Model->hincrbyField($RoomScore_Key,$mem_id, 0 - $score*count($winner_id)); //总分 减少
				 $xipai_score_dict[$mem_id] =  0 - $score*count($winner_id);
			 }
		 }
		 $this->writeLog("[$room_id]后积分：".json_encode($Redis_Model->hgetallField($RoomScore_Key)));
		 return $xipai_score_dict;
	 }
	/*
		一局输赢结果
		win_type 结局   1开牌   2弃牌    3封顶自动开牌
	*/

	public function showWin($room_id, $account_id, $next_account_id, $win_type){
		$success = $this->setRoomStatusTransaction($room_id, 2, 1);
		if(!$success){
			$this->writeLog("并发 showWin ，忽略。room id:".$room_id."。in file".__FILE__." on Line ".__LINE__);
			return false;
		}

		$Redis_Model = Redis_Model::getModelObject();
		
		$replyArr = array("[roomid]"=>$room_id);
		$PlayMember_Key = strtr(Redis_Const::PlayMember_Key, $replyArr);
		$players = $Redis_Model->lrangeList($PlayMember_Key);
		$Room_Key = strtr(Redis_Const::Room_Key, $replyArr);

		$player_cards = array();  //索引数组
		$winner_score_dict = array();
$xipaiScore = $this->queryXipaiScore($room_id);
		if(1 == $win_type){	//开牌结局

			$cards1 = $this->queryCardInfo($room_id, $account_id);
			$value1 = $this->_cardValue($cards1);

			$cards2 = $this->queryCardInfo($room_id, $next_account_id);
			$value2 = $this->_cardValue($cards2);

			if($value1 > $value2){
				$winner_id = $account_id;
				$card_type = substr($value1, 0, 1);
			} else {
				$winner_id = $next_account_id;
				$card_type = substr($value2, 0, 1);
			}
			$_card_type = $card_type;
			$player_cards[] = array(
				'account_id'=> $account_id,
				'cards' => $cards1
				); 
			$player_cards[] = array(
				'account_id'=> $next_account_id,
				'cards' => $cards2
				);

			if($winner_id > 0){
				$winner_score_dict = $this->balanceWinnerScore($room_id, [$winner_id], $account_id);
			}
			$winners[] = $winner_id;
		} else if(2 == $win_type){	//弃牌结局
			$winner_id = ($next_account_id != -1) ? $next_account_id : $account_id;
			$cards = $this->queryCardInfo($room_id, $winner_id);
			$value = $this->_cardValue($cards);
			$_card_type = substr($value, 0, 1);

			if ($_card_type >= 5 && $xipaiScore > 0){//判断是否喜牌并且开启喜牌
				$player_cards[] = array(
					'account_id'=> $winner_id,
					'cards' => $cards
				);
				$card_type = $_card_type;
			}else{
				$card_type = 0;
			}

			if($winner_id > 0){
				$winner_score_dict = $this->balanceWinnerScore($room_id, [$winner_id], $account_id);
			}
			$winners[] = $winner_id;
		} else { //封顶自动开牌

			$winners = array();
			$players = $Redis_Model->lrangeList($PlayMember_Key);
			$card_value_array = array();  //关联数组
			$max_value = 0;
			$_card_type = 0;
			foreach ($players as $player_id) {

				$cards = $this->queryCardInfo($room_id, $player_id);
				$value = $this->_cardValue($cards);
				$card_value_array[$player_id] = $value;
				if($value > $max_value){
					$max_value = $value;
					$card_type = substr($max_value, 0, 1);
					$_card_type = $card_type;
				}
				//手牌
				$player_cards[] = array(
					'account_id'=> $player_id,
					'cards' => $cards
					);
			}

			$this->writeLog("[$room_id] choose Winner:");
			foreach ($card_value_array as $winner_id => $value) {
				$this->writeLog("[$room_id] ".$winner_id." => ".$value);
				if($value == $max_value){
					$winners[] = $winner_id;
					$this->writeLog("[$room_id] --------------");
				}
			}
			$winner_score_dict = $this->balanceWinnerScore($room_id, $winners, $account_id);
		}
		$xipai_score_dict = [];
		$this->writeLog("[".$room_id."] _card_type:". $_card_type);
		$this->writeLog("[".$room_id."] player_cards:".json_encode($player_cards));
		if ($_card_type >=5 ){//判断是否喜牌并且开启喜牌
			$xipai_score_dict = $this->balanceXipaiScore($room_id, $winners);
		}
		if(count($winner_score_dict) > 0){

			$RoomScore_Key = strtr(Redis_Const::RoomScore_Key, $replyArr);
			$scoreboard = $Redis_Model->hgetallField($RoomScore_Key);

			//保存积分榜
			if(is_array($scoreboard)){
				$ticket_checked_user = $this->queryTicketCheckedUser($room_id);
				foreach ($scoreboard as $account_id => $score) {
					if(!in_array($account_id, $ticket_checked_user)){
						//未扣房卡的用户不显示在积分榜上
						unset($scoreboard[$account_id]);
					} 
				}
				$board_json_str = json_encode($scoreboard);

			} else {
				$scoreboard = array();
				$board_json_str = "";
			}
			$mkv[Redis_Const::Room_Field_Scoreboard] = $board_json_str;
			$Redis_Model->hmsetField($Room_Key,$mkv);


			$start_time = $this->queryStartTime($room_id);
			$game_num = $this->queryGameNumber($room_id);
			$total_num = $this->queryTotalNum($room_id);
			$msg_arr = array(
				'result' => 0,
				'operation' => 'Win',
				'result_message' => "获胜+积分榜",
				'data' => array(
					'player_cards' => $player_cards,
					'card_type' => $card_type,
					'score_board' => $scoreboard,
					'game_num' => $game_num,
					'total_num' =>  $total_num,
					'winner_score_dict' => $winner_score_dict,
					'xipai_score_dict'=>$xipai_score_dict,
					)
				);
			
			$this->pushMessageToGroup($room_id, $msg_arr);

			//保存当局游戏结果
			$setting = $this->queryRoomSetting($room_id);
			$round = $setting[Redis_Const::Room_Field_GameRound];

			$game_info['room_id'] = $room_id;
			$game_info['game_type'] = Game::Game_Type;
			$game_info['dealer_num'] = Config::Dealer_Num;
			$game_info['round'] = $round;
			$game_info['game_num'] = $game_num;
			$game_info['total_num'] = $total_num;
			$game_info['extra'] = "";
			$this->saveGameResult($game_info);


			//$this->updateRoomStatus($room_id, 1);   //房间状态，1等待、2进行中、3关闭
			if($game_num == $total_num){  //最后一局

				$MMYSQL = $this->initMysql();

				$round = $Redis_Model->hincrbyField($Room_Key, Redis_Const::Room_Field_GameRound, 1);
				$this->writeLog("[$room_id] 第".($round-1)."轮 结束!");

				$name_board = array();
				foreach ($scoreboard as $account_id => $score) {
					$account_sql = 'select nickname from '.WX_Account.' where account_id ='.$account_id;
					$name = $MMYSQL->single($account_sql);
					$name_board[] = array('name'=>$name, 'score'=>$score, 'account_id'=>$account_id);
					
				}

				//规则文本
				$rule_text = $this->formatRuleText($room_id);
				$balance_scoreboard = array('time'=>time(), 'scoreboard'=>$name_board,'game_num'=>$game_num);
				$balance_board_json_str = json_encode($balance_scoreboard['scoreboard']);
				//保存积分榜
				$board_array['start_time'] = $start_time;
				
				$board_array['create_time'] = time();
				$board_array['is_delete'] = G_CONST::IS_FALSE;
				$board_array['game_type'] = Game::Game_Type;  //游戏类型
				$board_array['room_id'] = $room_id;
				$board_array['round'] = $round-1;
				$board_array['game_num'] = $game_num;

				$board_array['rule_text'] = $rule_text;
				$board_array['board'] = $board_json_str;
				$board_array['balance_board'] = $balance_board_json_str;
				$board_id = $MMYSQL->insertReturnID(Room_Scoreboard,$board_array);

				//保存用户积分
				$game_info['score_board'] = $scoreboard;
				$this->saveAccountGameScore($game_info);

				//清理房间
				$this->clearRoom($room_id);

			} else {

				$this->resetAllAccountStatus($room_id);  //重设所有用户状态为未准备

				$Play_Key = strtr(Redis_Const::Play_Key, $replyArr);
				$PlayMember_Key = strtr(Redis_Const::PlayMember_Key, $replyArr);
				$Card_Key = strtr(Redis_Const::Card_Key, $replyArr);
				$Chip_Key = strtr(Redis_Const::Chip_Key, $replyArr);
				$SeenCard_Key = strtr(Redis_Const::SeenCard_Key, $replyArr);
				//删除每局游戏参数
				$Redis_Model->deleteKey($Play_Key);
				$Redis_Model->deleteKey($PlayMember_Key);
				$Redis_Model->deleteKey($Card_Key);
				$Redis_Model->deleteKey($Chip_Key);
				$Redis_Model->deleteKey($SeenCard_Key);
			}

		} else {
			$this->logMessage('error', "数据错误:function(openCard):have no winner!");
		}
	}

	protected function clearRoom($room_id){
		//清理房间
		$Redis_Model = Redis_Model::getModelObject();
		$replyArr = array("[roomid]"=>$room_id);

		$Room_Key = strtr(Redis_Const::Room_Key, $replyArr);
        $newRoomNumber = $Redis_Model->hgetField($Room_Key,Redis_CONST::Room_Field_NewNumber);
		$RoomScore_Key = strtr(Redis_Const::RoomScore_Key, $replyArr);
		$AccountStatus_Key = strtr(Redis_Const::AccountStatus_Key, $replyArr);
		
		$Play_Key = strtr(Redis_Const::Play_Key, $replyArr);
		$PlayMember_Key = strtr(Redis_Const::PlayMember_Key, $replyArr);
		$Card_Key = strtr(Redis_Const::Card_Key, $replyArr);
		$Chip_Key = strtr(Redis_Const::Chip_Key, $replyArr);
		$SeenCard_Key = strtr(Redis_Const::SeenCard_Key, $replyArr);
		
		//删除每轮游戏参数
		$Redis_Model->deleteKey(strtr(Redis_Const::RoomSequence_Key, $replyArr));
		$Redis_Model->deleteKey(strtr(Redis_Const::RoomGuest_Key, $replyArr));
		$Redis_Model->deleteKey($RoomScore_Key);
		$Redis_Model->deleteKey($AccountStatus_Key);
		//删除每局游戏参数
		$Redis_Model->deleteKey($Play_Key);
		$Redis_Model->deleteKey($PlayMember_Key);
		$Redis_Model->deleteKey($Card_Key);
		$Redis_Model->deleteKey($Chip_Key);
		$Redis_Model->deleteKey($SeenCard_Key);

		if(Config::Room_IsReuse == 1){	//可以重复利用房间
			$r_mkv[Redis_Const::Room_Field_GameNum] = 0;			//游戏局数
			$r_mkv[Redis_Const::Room_Field_DefaultScore] = Game::Default_Score;		//开局默认分数
			$r_mkv[Redis_Const::Room_Field_Scoreboard] = "";		//积分榜清零
			$r_mkv[Redis_Const::Room_Field_Creator] = -1;		//创建者清空
			$r_mkv[Redis_Const::Room_Field_Status] = Game::RoomStatus_Closed;	//房间状态，1等待、2进行中、3未激活
			$r_mkv[Redis_Const::Room_Field_StartTime] = -1;
			$mset_result = $Redis_Model->hmsetField($Room_Key,$r_mkv);
		} else {  //玩一轮即销毁
			$MMYSQL = $this->initMysql();
			$MMYSQL->update(Room)->set('is_close', '1')->where('room_id='.$room_id)->query();
            $RedisLog_Model = Redis_Model::getModelObjectLogs();
            $RedisLog_Model->hdelFiled(Redis_CONST::Room_New_Key,$newRoomNumber);
			$Redis_Model->deleteKey($Room_Key);
		}
		$this->writeLog("[$room_id] 房间清理完毕!");
	}

	//整理规则内容文本
	protected function formatRuleText($room_id,$room_data="")
	{
		$rule_text = "";
		$setting = $this->queryRoomSetting($room_id);
		$ticket_count=isset($setting[Redis_Const::Room_Field_TicketCount]) ?$setting[Redis_Const::Room_Field_TicketCount]:1;
		$chip_type= isset($setting[Redis_Const::Room_Field_ChipType])?$setting[Redis_Const::Room_Field_ChipType]:1;
		$disable_pk_score=isset($setting[Redis_Const::Room_Field_DisablePkScore]) ?$setting[Redis_Const::Room_Field_DisablePkScore]:0;
		$disable_pk_men=isset($setting[Redis_Const::Room_Field_DisablePkMen]) ?$setting[Redis_Const::Room_Field_DisablePkMen]:0;
		$disable_look=isset($setting[Redis_Const::Room_Field_DisableLook]) ?$setting[Redis_Const::Room_Field_DisableLook]:0;
		$upper_limit   =isset($setting[Redis_Const::Room_Field_UpperLimit]) ?$setting[Redis_Const::Room_Field_UpperLimit]:1000;
		$xipai_score   =isset($setting[Redis_Const::Room_Field_XiPai]) ?$setting[Redis_Const::Room_Field_XiPai]:0;
		//局数房卡规则
		$game_multi = Config::GameUser_MaxCount==9 ? 2 : 1;
		$ticket_count = $ticket_count * $game_multi * Config::Ticket_Multi;
		$ticket_type_text = $setting[Redis_Const::Room_Field_TotalNum]."局/".$ticket_count."张房卡";
		$rule_text .= $ticket_type_text;

		//筹码类型
		$rule_text .= ",";
		switch($chip_type)
		{
			case 1:
				$rule_text .= "筹码:2/5,4/10,8/20,10/25";
				break;
			case 2:
				$rule_text .= "筹码:4/10,8/20,10/25,20/50";
				break;
		}
		
		if($disable_pk_score )
		{
			$rule_text .= ",".$disable_pk_score."分以下不能比牌";
		}
		if($disable_pk_men )
		{
			$rule_text .= ",闷牌禁止比牌";
		}
		if($disable_look )
		{
			$rule_text .= ",首轮不能看牌";
		}

		//封顶上限
		if($upper_limit > 0){
			$rule_text .= ",上限:".$upper_limit."分";
		} else {
			$rule_text .= ",上限:无";
		}
		if($xipai_score > 0){
			$rule_text .= ",喜牌:".$xipai_score."分";
		} else {
			$rule_text .= ",喜牌:无";
		}
		return $rule_text;
	}


	/*
		保存炸金花游戏结果
	*/
	protected function saveGameResult($game_info)
	{
		$timestamp = time();
		$MMYSQL = $this->initMysql();
		$room_id = $game_info['room_id'];
		$game_type = $game_info['game_type'];

		$game_data['time'] = time();
		$game_data['rid'] = $game_info['room_id'];
		$game_data['rnd'] = $game_info['round'];
		$game_data['gnum'] = $game_info['game_num'];
		$game_data['tnum'] = $game_info['total_num'];

		//获取所有人手牌
		$Redis_Model = Redis_Model::getModelObject();
		$replyArr = array("[roomid]"=>$room_id);
		$Card_Key = strtr(Redis_Const::Card_Key, $replyArr);
		$card_array = $Redis_Model->hgetallField($Card_Key);

		$player_array = array();	//玩家当局数据

		$Chip_Key = strtr(Redis_Const::Chip_Key, $replyArr);
		$chip_array = $Redis_Model->hgetallField($Chip_Key);

		$room_members = $this->queryRoomMembers($room_id);

		//获取用户名字
		$names = array();
		if(count($room_members)>0){
			$account_sql = 'select account_id,nickname from '.WX_Account.' where account_id in ('.implode(",", $room_members).')';
			$rows = $MMYSQL->query($account_sql);
			if(is_array($rows)){
				foreach ($rows as $item) {
					$names[$item['account_id']] = $item['nickname'];
				}
			}
		}

		foreach($room_members as $player_id)
		{
			if(!isset($chip_array[$player_id]) || !isset($card_array[$player_id])){
				continue;
			}

			$array['p'] = $player_id;
			$array['s'] = $chip_array[$player_id];
			$array['c'] = $card_array[$player_id];
			
			$card_type = "1";
			$value = $this->caculateCardValue($room_id, $player_id);
			$card_type = substr($value, 0, 1);

			$array['ct'] = $card_type;

			//获取用户名字
			$array['n'] = isset($names[$player_id])?$names[$player_id]:"";

			$player_array[] = $array;
			unset($array);
		}

		$save_game_result['pAry'] = $player_array;
		$save_game_result['gData'] = $game_data;
		$save_game_result_json = json_encode($save_game_result);

		$round = $game_data['rnd'];
		$array['create_time'] = $timestamp;
		$array['game_type'] = $game_type;
		$array['room_id'] = $room_id;
		$array['round'] = $round;
		$array['game_result'] = $save_game_result_json;

		$result_id = $MMYSQL->insertReturnID(Room_GameResult,$array);
		unset($array);
		return true;
	}

	protected function saveAccountGameScore($game_info)
	{
		$timestamp = time();
		$MMYSQL = $this->initMysql();
		$cols = array('create_time','game_time','is_delete','room_id','game_type','round','account_id','score');
		if(is_array($game_info['score_board'])){
			$values = array();
			foreach ($game_info['score_board'] as $account_id => $score) {
				$values[] = array($timestamp, $timestamp, 0, $game_info['room_id'], $game_info['game_type'], $game_info['round'], $account_id, $score);
			}
			$MMYSQL->insertRows(Room_GameScore, $cols, $values);
		}
	}


	//发牌 全随机规则
	protected function dealCard($player_count){
		$player_cards = array();
		$Card = array("A1","A2","A3","A4","A5","A6","A7","A8","A9","A10","A11","A12","A13",
						  "B1","B2","B3","B4","B5","B6","B7","B8","B9","B10","B11","B12","B13",
						  "C1","C2","C3","C4","C5","C6","C7","C8","C9","C10","C11","C12","C13",
						  "D1","D2","D3","D4","D5","D6","D7","D8","D9","D10","D11","D12","D13"
						  );
		mt_srand();
		$indexs = array_rand($Card, 3 * $player_count);
		shuffle($indexs);
		$num = 0;
		for ($i=0; $i < $player_count; $i++) {
			$card_str = $Card[$indexs[$num]].','. $Card[$indexs[$num+1]] .','.$Card[$indexs[$num+2]];
			$player_cards[] = $card_str;
			$num += 3;
			$this->writeLog($card_str);
		}
//		$staticCards = [
//			"A1,B1,C1",
//			"D4,B2,C3",
//			"A2,A3,A4",
//			"B3,B4,B5",
//			"D5,D6,D7",
//			"D12,D13,D1",
//			"A12,B12,C13",
//			"A10,B10,C10",
//		];
//		shuffle($staticCards);
//		for ($i=0; $i < $player_count; $i++) {
//			$player_cards[]=$staticCards[$i];
//		}
		return $player_cards;
	}


	/*
		推给定时器服务器
	*/
	public function sendToTimerServer($msg_array = "")
	{
		$message = $this->_JSON($msg_array);

		$socket_name = "Timer";
		$Socket_Model = Socket_Model::getModelObject($socket_name);
		$Socket_Model->sendMessageToSocket($socket_name,$message);

		return true;
	}


	/*
		数组转JSON格式
	*/
	protected function _JSON($array) 
	{  
		$this->__arrayRecursive($array, 'urlencode', true);  
		$json = json_encode($array);  
		return urldecode($json);  
	}
	private function __arrayRecursive(&$array, $function, $apply_to_keys_also = false)  
	{  
		static $recursive_counter = 0;  
		if (++$recursive_counter > 1000) {  
			$this->logMessage('error', "function(_JSON):recursive_counter>1000"." in file".__FILE__." on Line ".__LINE__);
			return;
			die('possible deep recursion attack');  
		}  
		foreach ($array as $key => $value) {  
			if (is_array($value)) {  
				$this->__arrayRecursive($array[$key], $function, $apply_to_keys_also);  
			}
			else if(is_object($value))
			{
				$array[$key] = $value;
			} 
			else 
			{  
				$array[$key] = $function($value);  
			}  
	   
			if ($apply_to_keys_also && is_string($key)) {  
				$new_key = $function($key);  
				if ($new_key != $key) {  
					$array[$new_key] = $array[$key];  
					unset($array[$key]);  
				}  
			}  
		}  
		$recursive_counter--;
	}   
	
	/**
    * 拆解接收的json字符串
    * @param string $splitJsonString json字符串
    */
	protected function _splitJsonString($jsonString)
	{
		if(empty($jsonString))
		{
			return OPT_CONST::JSON_FALSE;
		}
		//判断是否为JSON格式
		if(is_null(json_decode($jsonString)))
		{
			//不是json格式
			return OPT_CONST::JSON_FALSE;
		}
		else
		{
			//分拆JSON字符串
			return json_decode($jsonString,true);
		}
	}
	
	
	/*
		返回缺参结果
	*/
	protected function _missingPrameterArr($operation,$prameter)
	{
		return array('result'=>OPT_CONST::MISSING_PARAMETER,'operation'=>$operation,'data'=>array("missing_parameter"=>$prameter),'result_message'=>"缺少参数");
	}
	
	
	
	/*
		判断数据格式是否正确
	*/
	protected function _checkRequestFormat($requestAry)
	{
		if(!isset($requestAry['msgType']))
		{
			$this->logMessage('error', "function(checkRequestFormat):lack of msgType"." in file".__FILE__." on Line ".__LINE__);
			return array('result'=>-20,'operation'=>"",'data'=>array("missing_parameter"=>"msgType"),'result_message'=>"缺少参数");
		}
		if(!isset($requestAry['content']))
		{
			$this->logMessage('error', "function(checkRequestFormat):lack of content"." in file".__FILE__." on Line ".__LINE__);
			return array('result'=>-20,'operation'=>"",'data'=>array("missing_parameter"=>"content"),'result_message'=>"缺少参数");
		}
		
		return OPT_CONST::POSTARRAY_TRUE;
	}
	
	
	/*
		判断数据格式是否正确
	*/
	protected function _checkPostArray($postArr)
	{
		
		if(!isset($postArr['operation']))
		{
			$this->logMessage('error', "function(checkPostArray):lack of operation"." in file".__FILE__." on Line ".__LINE__);
			return array('result'=>-20,'operation'=>"",'data'=>array(),'result_message'=>"缺少参数");
		}
		else $operation = $postArr['operation'];
		if(!isset($postArr['data']))
		{
			$this->logMessage('error', "function(checkPostArray):lack of data"." in file".__FILE__." on Line ".__LINE__);
			return array('result'=>-20,'operation'=>$operation,'data'=>array(),'result_message'=>"缺少参数");
		}
		if(!isset($postArr['account_id']))
		{
			$this->logMessage('error', "function(checkPostArray):lack of account_id"." in file".__FILE__." on Line ".__LINE__);
			return array('result'=>-20,'operation'=>$operation,'data'=>array(),'result_message'=>"缺少参数");
		}
		if(!isset($postArr['session']))
		{
			$this->logMessage('error', "function(checkPostArray):lack of session"." in file".__FILE__." on Line ".__LINE__);
			return array('result'=>-20,'operation'=>$operation,'data'=>array(),'result_message'=>"缺少参数");
		}
		return OPT_CONST::POSTARRAY_TRUE;
	}
	
	
	
	/*
		生成微秒
	*/
	protected function getMicroTimestamp()
	{
		$mtime=explode(' ',microtime());
		$mTimestamp=$mtime[1] . substr($mtime[0],2,3);
		
		return $mTimestamp;
	}
	
	/*
		判断请求链接合法性
	*/
	protected function checkRequestClientLegal($client_id,$room_id,$account_id)
	{
		return true;
		//绑定用户UID
		$replyArr = array("[roomid]"=>$room_id,"[accountid]"=>$account_id);
		$room_aid = strtr(Game::RoomUser_UID, $replyArr);

		$client_array = Gateway::getClientIdByUid($room_aid);
		if(is_array($client_array) && count($client_array) > 0)
		{
			foreach($client_array as $bind_client)
			{
				if($bind_client == $client_id)
				{
					return true;
				}
			}
		}
		return false;
	}
	

	//离开座位的加锁函数  (离线回调或观战方法调用)
	protected function leaveSeatTransaction($room_id,$account_id){
		$Redis_Model = Redis_Model::getModelObject();
		$replyArr = array("[roomid]"=>$room_id);
		$key = strtr(Redis_Const::RoomSequence_Key, $replyArr);
		$redisAuth = $Redis_Model->pingRedisAuth();
		if($redisAuth === G_CONST::EMPTY_STRING || !is_object($redisAuth)){
			$this->logMessage('error', "function(joinRoomTransaction):redisAuth is empty string"." in file".__FILE__." on Line ".__LINE__);
			return false;
		}
	    $success = 0;
	    $options = array(
	        'cas'   => true,    // Initialize with support for CAS operations
	        'watch' => $key,    // Key that needs to be WATCHed to detect changes
	        'retry' => 3,       // Number of retries on aborted transactions, after
	                            // which the client bails out with an exception.
	    );
	    $redisAuth->transaction($options, function ($tx) use ($key,$account_id, &$success) {
	    	$result = $tx->zrange($key,0,-1,'withscores');
	    	if(is_array($result)) {
	    		if(isset($result[$account_id])){ //checked 离座
	    			$success = 1;
	    		} else if(isset($result[-$account_id])){ //unchecked 离座
	    			$tx->zrem($key, -$account_id);
	    			$success = 2;
	    		}
	    	}
	    });
	    return $success;
	}

	//开始一局时检票
	protected function ticketCheckTransaction($room_id, $ready_in_room_user){
		$ret_array = array();	
		$Redis_Model = Redis_Model::getModelObject();
		$replyArr = array("[roomid]"=>$room_id);
		$key = strtr(Redis_Const::RoomSequence_Key, $replyArr);
		$redisAuth = $Redis_Model->pingRedisAuth();
		if($redisAuth === G_CONST::EMPTY_STRING || !is_object($redisAuth)){
			$this->logMessage('error', "function(joinRoomTransaction):redisAuth is empty string"." in file".__FILE__." on Line ".__LINE__);
			return $ret_array;
		}
	    $options = array(
	        'cas'   => true,    // Initialize with support for CAS operations
	        'watch' => $key,    // Key that needs to be WATCHed to detect changes
	        'retry' => 3,       // Number of retries on aborted transactions, after
	                            // which the client bails out with an exception.
	    );
	    $redisAuth->transaction($options, function ($tx) use ($key, $ready_in_room_user, &$ret_array) {
	    	$result = $tx->zrange($key,0,-1,'withscores');
	    	if(is_array($result)) {
	    		$ret_array = array_keys($result);
	    		$unchecked_arr = array();
	    		foreach ($result as $account_id => $serial_num) {
	    			if($account_id < 0 && in_array(-$account_id, $ready_in_room_user)){
	    				$unchecked_arr[$account_id] = $serial_num;
	    			}
	    		}
	    		if(count($unchecked_arr) > 0){
	    			foreach ($unchecked_arr as $account_id => $serial_num) {
	    				$tx->zadd($key, $serial_num, -$account_id);
	    			}
	    			$unchecked_account_id = array_keys($unchecked_arr);
	    			foreach ($unchecked_account_id as $account_id) {
	    				$tx->zrem($key, $account_id);
	    			}
	    			for ($i=0; $i < count($ret_array); $i++) { 
	    				if($ret_array[$i] < 0){
	    					$ret_array[$i] = -$ret_array[$i];
	    				}
	    			}
	    		}
	    	}
	    });
	    $ret_array = array_intersect($ready_in_room_user, $ret_array);
	    return $ret_array;
	}
	
	//获取玩家的座位号  从1开始，-1表示未入座
	protected function querySerialNum($room_id, $account_id){
		$Redis_Model = Redis_Model::getModelObject();
		$replyArr = array("[roomid]"=>$room_id);
		$RoomSequence_Key = strtr(Redis_Const::RoomSequence_Key, $replyArr);
		$zrange_array['is_zrange'] = true;
		$zrange_array['key'] = $RoomSequence_Key;
		$zrange_array['start'] = 0;
		$zrange_array['stop'] = -1;
		$zrange_array['WITHSCORES'] = true;
		$members = $Redis_Model->zrangeSet($zrange_array);
		if(!is_array($members)){
			return -1;
		}
		if(isset($members[$account_id])){
			return $members[$account_id];
		} else if(isset($members[-$account_id])){
			return $members[-$account_id];
		} else {
			return -1;
		}
	}

	//获取房间用户有序集合
	protected function queryRoomMembers($room_id, $withscores=false){
		$Redis_Model = Redis_Model::getModelObject();
		$replyArr = array("[roomid]"=>$room_id);
		$RoomSequence_Key = strtr(Redis_Const::RoomSequence_Key, $replyArr);
		$zrange_array['is_zrange'] = true;
		$zrange_array['key'] = $RoomSequence_Key;
		$zrange_array['start'] = 0;
		$zrange_array['stop'] = -1;
		if($withscores){
			$zrange_array['WITHSCORES'] = true;
		}
		$result = $Redis_Model->zrangeSet($zrange_array);
		$members = array();
		if(is_array($result) ){
			if($withscores){
				foreach ($result as $account_id => $serial_num) {
					if($account_id < 0){
						$account_id = -$account_id;
					}
					$members[$account_id] = $serial_num;
				}
			} else {
				foreach ($result as $account_id) {
					if($account_id < 0){
						$account_id = -$account_id;
					}
					$members[] = $account_id;
				}
			}
			return $members;
		} else {
			return array();
		}
	}

	//获取用户是否已经扣除房卡
	protected function queryTicketChecked($room_id, $account_id){
		$Redis_Model = Redis_Model::getModelObject();
		$replyArr = array("[roomid]"=>$room_id);
		$RoomSequence_Key = strtr(Redis_Const::RoomSequence_Key, $replyArr);
		$result = $Redis_Model->getZscore($RoomSequence_Key, $account_id);
		if($result > 0){
			return 1;
		} else {
			return 0;
		}
	}

	//获取checked的人
	protected function queryTicketCheckedUser($room_id){
		$Redis_Model = Redis_Model::getModelObject();
		$replyArr = array("[roomid]"=>$room_id);
		$RoomSequence_Key = strtr(Redis_Const::RoomSequence_Key, $replyArr);
		$zrange_array['is_zrange'] = true;
		$zrange_array['key'] = $RoomSequence_Key;
		$zrange_array['start'] = 0;
		$zrange_array['stop'] = -1;
		$result = $Redis_Model->zrangeSet($zrange_array);
		
		$user_array = array();
		if(Redis_CONST::DATA_NONEXISTENT !== $result){
			foreach ($result as $account_id) {
				if($account_id > 0){
					$user_array[] = $account_id;
				}
			}
		}
		return $user_array;
	}
	
}
?>

